home *** CD-ROM | disk | FTP | other *** search
- /*
- program SpaceAliens;
- (* Space Aliens Ate My Icons *)
- (* A drag and drop utility to fix the type and *)
- (* creator of any dropped on file based on its *)
- (* extension and the database of extension mappings *)
- (* provided by Internet Config. *)
-
- uses
- (* standard system units needed to do AppleEvents *)
- (* remember that Think Pascal automatically uses *)
- (* most of the base operating system *)
- */
-
- #include <EPPC.h>
- #include <AppleEvents.h>
- #include <Limits.h>
-
- // (* standard IC units *)
- #include "ICTypes.h"
- #include "ICAPI.h"
- #include "ICKeys.h"
-
- // Function Prototypes
- ICError ICGetPrefStr(ICInstance inst,const StringPtr key,ICAttr* attr,StringPtr str);
- OSErr GotRequiredParams(AppleEvent* theAppleEvent);
- OSErr ICMapErr(ICError err);
- StringPtr CopyStr(StringPtr dest,StringPtr src,short start, short end);
- OSErr ProcessDocument(FSSpec* fss);
- pascal OSErr HandleOpenApplication(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon);
- pascal OSErr HandleOpenDocuments(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon);
- pascal OSErr HandleQuit(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon);
- void main(void);
- OSErr ForceFinderUpdate(FSSpec *pFSS, Boolean flush);
-
- // (* ***** Standard Subroutines ***** *)
-
- ICError ICGetPrefStr(ICInstance inst,const StringPtr key,ICAttr* attr,StringPtr str){
- ICError err;
- long size=256L;
-
- err=ICGetPref(inst,key,attr,(Ptr)str,&size);
- if (err!=noErr)
- str[0]=0;
-
- return err;
- }
-
- OSErr GotRequiredParams(AppleEvent* theAppleEvent){
- DescType typeCode;
- Size actualSize;
- OSErr err;
-
- err=AEGetAttributePtr(theAppleEvent,keyMissedKeywordAttr,typeWildCard,&typeCode,nil,0,&actualSize);
- if (err==errAEDescNotFound)
- return noErr;
-
- if (err==noErr)
- return errAEEventNotHandled;
-
- return err;
- }
-
- OSErr ICMapErr(ICError err){
- return (OSErr)err;
- }
-
- #define my_creator 'SA8I' // (* the application signature *)
-
- Boolean quit_now; // set to true when you want main loop to quit
- ICInstance instance; // global connection to IC
- Handle mappings; // the mapping preference as returned by IC
-
- StringPtr CopyStr(StringPtr dest,StringPtr src,short start, short end){
-
- if (start>src[0]){
- // then trying to copy bytes that don't exist
- dest[0]=0;
- goto CopyStrEnd;
- }
- if (end<start){
- // then trying to copy negative or zero bytes
- dest[0]=0;
- goto CopyStrEnd;
- }
- if (end>src[0]){
- // shorten end since we really don't need those bytes
- end=src[0];
- }
-
- // Now do the copy
- BlockMoveData((Ptr)&(src[start]),(Ptr)&(dest[1]),(end-start)+1);
-
- // set up the len
- dest[0]=(end-start)+1;
-
- CopyStrEnd:
- return dest;
- }
-
- // (* ***** Do The Hard Stuff ***** *)
-
- OSErr ProcessDocument(FSSpec* fss){
- /*
- This is the core of the program. The fss parameter is a file whose extension
- we'll look up in the IC database. Mappings global variable is already set up to contain that database.
- */
-
- ICError err;
- long count,i,posndx,matchpos,curpos; // count is # database entries, posndx is index into database
- ICMapEntry this,entry; // this is unpacked element used in loops, entry is element with best match
- short longest_len; // longest extension found so far
- FInfo info; // temp to change type/creator
- Str255 tmp;
-
- // count the total number of entries
- err=ICCountMapEntries(instance,mappings,&count);
- if (err!=noErr)
- count=0;
-
- // loop through the series looking for the longest match
- longest_len=0;
- posndx=0;
- matchpos=-1;
-
- for (i=0;i<count;i++){
- curpos=posndx; // save current position
-
- // ICMGetEntry gets the entry from mappings that starts at posndx and puts into entry record
- if (ICGetMapEntry(instance,mappings,posndx,&this)==(ICError)noErr){
- // increment posndx so that we get the next entry the next time around the loop
- posndx+=this.total_length;
-
- // the entry matches if not_incoming flag bit is clear, it's longer than the previous max, it's longer
- // than the file name, and it matches the last N chars of the file name
-
- if ((!(this.flags&ICmap_not_incoming_mask))&&(this.extension[0]>longest_len)&&(this.extension[0]<fss->name[0])&&
- (IUEqualString(CopyStr(tmp,fss->name,fss->name[0]-this.extension[0]+1,255),this.extension)==0)){
- // record the new longest entry
- matchpos=curpos; // save the pos
- longest_len=this.extension[0];
- }
- }
- }
-
- if (matchpos!=-1){
- // then a match was found, reget the entry
- ICGetMapEntry(instance,mappings,matchpos,&entry);
-
- // now set the type/creator for the file
- err=HGetFInfo(fss->vRefNum,fss->parID,fss->name,&info);
- if (err==noErr){
- info.fdCreator=entry.file_creator;
- info.fdType=entry.file_type;
- err=HSetFInfo(fss->vRefNum,fss->parID,fss->name,&info);
- ForceFinderUpdate(fss,false);
- }
- } else
- err=noErr;
-
- quit_now=true;
- return err;
- }
-
- // (* ***** AppleEvent Handlers ***** *)
-
- pascal OSErr HandleOpenApplication(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon){
- // the 'oapp' event handler displays the about box
- // should most probably only do this if we're in the foreground but
- // that's just too complicated for this example
-
- OSErr err;
- Str255 email_address;
- long junk_attr;
-
- err=GotRequiredParams(theAppleEvent);
- if (err==noErr){
- ICGetPrefStr(instance,kICEmail,&junk_attr,email_address);
- ParamText(email_address,"\p","\p","\p");
- Alert(128,(ModalFilterUPP)0);
- quit_now=true;
- }
-
- return err;
- }
-
- pascal OSErr HandleOpenDocuments(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon){
- // a fairly standard 'odoc' event handler
- // gets the document list, counts the items in it
- // gets the fsspec for each document and calls ProcessDocument on it
-
- FSSpec fss;
- AEDescList doc_list;
- long index,item_count;
- Size junk_size;
- AEKeyword junk_keyword;
- DescType junk_type;
- OSErr err;
-
- err=AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&doc_list);
- if (err==noErr){
- err=GotRequiredParams(theAppleEvent);
- if (err==noErr)
- err=AECountItems(&doc_list,&item_count);
- else
- item_count=0;
-
- for (index=0;index<item_count;index++){
- if (err==noErr){
- err=AEGetNthPtr(&doc_list,index+1,typeFSS,&junk_keyword,&junk_type,&fss,sizeof(FSSpec),&junk_size);
- if (err==noErr)
- err=ProcessDocument(&fss);
- }
- }
- AEDisposeDesc(&doc_list);
- }
- return err;
- }
-
- pascal OSErr HandleQuit(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon){
- // a fairly standard 'quit' event handler
- // sets quit_now so that the main event loop quits
- OSErr err;
-
- err=GotRequiredParams(theAppleEvent);
- if (err==noErr)
- quit_now=true;
-
- return err;
- }
-
- /*
- ForceFinderUpdate() From DropShell 2.0
-
- This routine is used to force the Finder (as much as is possible) to update
- information about a newly changed file or folder.
- It does this by changing the modification date of the surrounding folder.
- */
- OSErr ForceFinderUpdate(FSSpec *pFSS, Boolean flush){
- OSErr lErr;
- CInfoPBRec lCBlk;
-
- if (pFSS->parID != 1) // if it's a vol then reuse the NameStr
- lCBlk.dirInfo.ioNamePtr = 0L;
- lCBlk.dirInfo.ioVRefNum = pFSS->vRefNum;
- lCBlk.dirInfo.ioDrDirID = pFSS->parID;
- lCBlk.dirInfo.ioFDirIndex = 0;
- lCBlk.dirInfo.ioCompletion = 0;
-
- lErr = PBGetCatInfoSync(&lCBlk);
- if (!lErr) {
- GetDateTime(&lCBlk.dirInfo.ioDrMdDat);
- lCBlk.dirInfo.ioDrDirID = pFSS->parID;
- lErr = PBSetCatInfoSync(&lCBlk);
-
- if ((!lErr) && (flush))
- lErr = FlushVol(nil, pFSS->vRefNum);
- }
-
- return (lErr);
- }
-
- void main(void){
- EventRecord event;
- OSErr err;
- long response;
- ICAttr attr;
- AEEventHandlerUPP odocu,oappu,quitu;
- short i;
-
- // Initialize the toolbox
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
-
- MaxApplZone();
-
- for (i=0;i<4;i++)
- MoreMasters();
-
- // FlushEvents(everyEvent,0);
-
- // first check for System 7. Ok, so we're supposed to test for functionality but this is example code
-
- err=Gestalt(gestaltSystemVersion,&response);
-
- if ((err!=noErr)||(response<0x0700))
- ExitToShell();
-
- // now install our AppleEvent handlers
- odocu=NewAEEventHandlerProc(HandleOpenDocuments);
- oappu=NewAEEventHandlerProc(HandleOpenApplication);
- quitu=NewAEEventHandlerProc(HandleQuit);
-
- err=AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,oappu,0,false);
- if (err==noErr)
- err=AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,odocu,0,false);
- if (err==noErr)
- err=AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,quitu,0,false);
-
- // start Internet Config
- if (err==noErr){
- err=ICMapErr(ICStart(&instance,my_creator));
- if (err==noErr)
- err=ICMapErr(ICFindConfigFile(instance,0,nil));
- }
-
- // fetch the mappings preference
- if (err==noErr)
- err=ICMapErr(ICGetPrefHandle(instance,kICMapping,&attr,&mappings));
-
- // enter main loop
- if (err==noErr){
- quit_now=false;
- while (!quit_now){
- WaitNextEvent((keyDownMask+highLevelEventMask),&event,100,(RgnHandle)0);
- switch (event.what){
- case keyDown:
- quit_now=true;
- break;
- case kHighLevelEvent:
- AEProcessAppleEvent(&event);
- break;
- default:
- break;
- }
- }
- // shut down IC only if we started it successfully
- ICStop(instance);
- }
-
- // beep if we get any errors
- // sophisticated error handling this is not
- // a good place to put a breakpoint this is
-
- if (err!=noErr)
- SysBeep(10);
- }
-